package edu.northwestern.cbits.purple_robot_manager.plugins; import java.io.IOException; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import android.annotation.SuppressLint; import android.content.ContentProviderOperation; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.OperationApplicationException; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; import android.support.v4.content.LocalBroadcastManager; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import edu.northwestern.cbits.purple_robot_manager.RobotContentProvider; import edu.northwestern.cbits.purple_robot_manager.activities.StartActivity; import edu.northwestern.cbits.purple_robot_manager.logging.LogManager; import edu.northwestern.cbits.purple_robot_manager.models.Model; import edu.northwestern.cbits.purple_robot_manager.models.ModelManager; import edu.northwestern.cbits.purple_robot_manager.probes.Probe; public class AppDisplayPlugin extends OutputPlugin { private long _lastUpdate = 0; private final ArrayList<ContentValues> _valuesQueue = new ArrayList<>(); private final HashMap<String, Long> _lastUpdates = new HashMap<>(); public String[] respondsTo() { String[] activeActions = { Probe.PROBE_READING, OutputPlugin.LOG_EVENT, AppDisplayPlugin.DISPLAY_MESSAGE }; return activeActions; } @SuppressLint("NewApi") public void processIntent(final Intent intent) { Bundle extras = intent.getExtras(); final Context context = this.getContext(); if (AppDisplayPlugin.DISPLAY_MESSAGE.equals(intent.getAction())) { Intent displayIntent = new Intent(StartActivity.UPDATE_MESSAGE); displayIntent.putExtra(StartActivity.DISPLAY_MESSAGE, extras.getString("MESSAGE")); LocalBroadcastManager manager = LocalBroadcastManager.getInstance(context); manager.sendBroadcast(displayIntent); } else { String source = extras.getString("PROBE"); Long updated = this._lastUpdates.get(source); if (updated == null) updated = 0L; long now = System.currentTimeMillis(); if (now - updated < 1000) return; // Only record a sample once a second for display purposes... this._lastUpdates.put(source, now); final ContentValues values = new ContentValues(); Object ts = extras.get("TIMESTAMP"); if (ts instanceof Long) values.put("recorded", (Long) ts); else if (ts instanceof Double) values.put("recorded", ((Double) ts).longValue()); values.put("source", source); if (extras.containsKey("FROM_MODEL")) { Model m = ModelManager.getInstance(context).fetchModelByTitle(context, extras.getString("PROBE")); values.put("source", m.name(context)); } try { JsonFactory factory = new JsonFactory(); StringWriter outputWriter = new StringWriter(); JsonGenerator generator = factory.createGenerator(outputWriter); StreamingJacksonUploadPlugin.writeBundle(this.getContext(), generator, extras); generator.close(); values.put("value", outputWriter.toString()); } catch (IOException e) { LogManager.getInstance(context).logException(e); } ContentValues toRemove = null; synchronized (this._valuesQueue) { do { toRemove = null; for (ContentValues check : this._valuesQueue) { if (check.getAsString("source").equals(values.getAsString("source"))) toRemove = check; } if (toRemove != null) this._valuesQueue.remove(toRemove); } while (toRemove != null); this._valuesQueue.add(values); } if (now - this._lastUpdate > 1000) { this._lastUpdate = System.currentTimeMillis(); final ArrayList<ContentValues> toUpdate = new ArrayList<>(); synchronized (this._valuesQueue) { while (this._valuesQueue.size() > 0) { toUpdate.add(this._valuesQueue.remove(0)); } } Handler mainHandler = new Handler(context.getMainLooper()); mainHandler.post(new Runnable() { public void run() { String where = "source = ?"; ArrayList<ContentProviderOperation> ops = new ArrayList<>(); for (ContentValues value : toUpdate) { String[] whereArgs = { value.getAsString("source") }; ContentProviderOperation.Builder update = ContentProviderOperation .newUpdate(RobotContentProvider.RECENT_PROBE_VALUES) .withSelection(where, whereArgs).withValues(value); ops.add(update.build()); } try { context.getContentResolver().applyBatch(RobotContentProvider.AUTHORITY, ops); } catch (RemoteException | OperationApplicationException e) { LogManager.getInstance(context).logException(e); } context.getContentResolver().notifyChange(RobotContentProvider.RECENT_PROBE_VALUES, null); } }); } } } }